home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-12-19 | 50.6 KB | 1,760 lines |
- Newsgroups: comp.sources.unix
- From: clyde@emx.utexas.edu (Clyde Hoover)
- Subject: v25i075: npasswd - replacement for passwd(1), Part02/03
- Sender: sources-moderator@pa.dec.com
- Approved: vixie@pa.dec.com
-
- Submitted-By: clyde@emx.utexas.edu (Clyde Hoover)
- Posting-Number: Volume 25, Issue 75
- Archive-Name: npasswd/part02
-
- From clyde@emx.utexas.edu Fri Jan 25 12:45:25 1991
- Received: from BBN.COM by pineapple.bbn.com id <AA22522@pineapple.bbn.com>; Fri, 25 Jan 91 12:45:04 -0500
- Received: from uunet.UU.NET by BBN.COM id aa03147; 25 Jan 91 12:38 EST
- Received: from cs.utexas.edu by uunet.uu.net (5.61/1.14) with SMTP
- id AA17158; Fri, 25 Jan 91 12:38:31 -0500
- Received: from emx.utexas.edu by cs.utexas.edu (5.64/1.93) via SMTP
- id AA17940; Fri, 25 Jan 91 11:37:52 -0600
- Posted-Date: 25 Jan 91 17:02:50 GMT
- Received: by emx.utexas.edu (5.61/1.8)
- id AA04098; Fri, 25 Jan 91 11:02:54 -0600
- To: comp-sources-unix@emx.utexas.edu
- Path: ut-emx!clyde
- From: Head UNIX Hacquer <ut-emx!clyde@emx.utexas.edu>
- Newsgroups: comp.sources.unix
- Subject: npasswd, a replacement for passwd(1) (part 2 of 3)
- Keywords: Password changing program
- Message-Id: <43165@ut-emx.uucp>
- Date: 25 Jan 91 17:02:50 GMT
- Organization: Moose & Squirrel Software
- Lines: 1725
- Status: R
-
-
- Npasswd is a pretty-much-plug-compatable replacement for passwd(1).
- This version incorporates a password checking system
- that disallows simple-minded passwords.
-
- It does exactly ONE thing - change login passwords, though it would
- not be too difficult to make it do shells and GECOS stuff also.
-
- I have modeled npasswd after passwd(1) from 4.3BSD and SunOS 4.0, but
- it does not impliment the options those versions have.
- I have also included support for Sys VR3 password aging.
-
- This version runs at our site under SunOS 4.X, Ultrix 4.0, UMAX 4.3 and
- MORE/BSD.
-
- It is also available via anonymous FTP from emx.utexas.edu in the directory
- pub/npasswd.
-
- ----------- cut here -----------
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 2 (of 3)."
- # Contents: Makefile.dist checkpasswd/README checkpasswd/checkpasswd.8
- # checkpasswd/pwck_dict.c checkpasswd/pwck_lexical.c pw_passwd.c
- # pw_userinfo.c
- # Wrapped by clyde@tigger.cc.utexas.edu on Fri Jan 25 10:35:07 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'Makefile.dist' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Makefile.dist'\"
- else
- echo shar: Extracting \"'Makefile.dist'\" \(7149 characters\)
- sed "s/^X//" >'Makefile.dist' <<'END_OF_FILE'
- X
- X# -------------------------------------------------------------------- #
- X# #
- X# Author: Clyde Hoover #
- X# Computation Center #
- X# The University of Texas at Austin #
- X# Austin, Texas 78712 #
- X# clyde@emx.utexas.edu #
- X# uunet!cs.utexas.edu!ut-emx!clyde #
- X# #
- X#This code may be distributed freely, provided this notice is retained. #
- X# #
- X# -------------------------------------------------------------------- #
- X#
- X# Makefile for npasswd
- X
- X# @(#)Makefile.dist 1.11 11/26/90 (cc.utexas.edu)
- X
- X# Top of install tree
- XDEST =
- X
- X# Where the binary lives
- XBINDIR = /bin
- X
- X# Where condfiguration files live
- XADMDIR = /usr/adm
- X
- X# Where manual pages live
- XMANDIR = /usr/man/man1
- X
- X# Mode for binary
- XIMODE = 4511
- X
- X# Name of binary
- XPASSWD = npasswd
- X
- X# Things to build in subdirectories
- XSUBDIRS = checkpasswd
- X
- X# Name of password check library
- XCHKLIB = checkpasswd/checkpasswd.a
- X
- X# Name of distribution files
- XDISTNAME = npasswd
- X
- X# Name of library to get Sun RPC client routines from
- XLIB_RPCSVC = -lrpcsvc
- X
- X# Flags to pass down to password checker
- XCHECKPW_FLAGS =
- X
- X# ---------------------------------------------------------------
- X# Npasswd configuration
- X# ---------------------------------------------------------------
- X
- X# The password file location
- X# PWF = /etc/passwd
- X
- X# The temp and lock file for passwd file changes
- X# PWT = /etc/ptmp
- X
- X# The saved password file
- X# PWS = /etc/opasswd
- X
- X# PWFD = -DPASSWD_FILE=\"$(PWF)\"
- X# PWTD = -DPASSWD_TEMP=\"$(PWT)\"
- X# PWSD = -DPASSWD_SAVE=\"$(PWS)\"
- X
- X# The configuration file
- XCF = $(DEST)$(ADMDIR)/$(PASSWD).conf
- XCFD = -DCONFIG_FILE=\"$(CF)\"
- X
- X# The help file
- XHF = $(DEST)$(ADMDIR)/$(PASSWD).help
- XHFD = -DHELP_FILE=\"$(HF)\"
- X
- X# The message file
- XMF = $(DEST)$(ADMDIR)/$(PASSWD).motd
- XMFD = -DMOTD_FILE=\"$(MF)\"
- X
- X# ---------------------------------------------------------------
- X# Enable only ONE of the following options
- X# ---------------------------------------------------------------
- X
- X#
- X# Ultrix 4.0 (highly mutated 4.2)
- X# ULTRIX = -DBSD4_3 -DNDBM -DNO_CLNT_SPERRNO -DXFGETPWENT -DXPUTPWENT
- X# LIB_RPCSVC =
- X
- X# Using 4.3BSD hashed password file
- X# BSD = -DBSD4_3 -DNDBM
- X
- X# Running under System V
- X# SYS5 = -DSYSV
- X
- X# If running under SunOS 4.X (funky tty ioctls)
- X# SUNOS = -DSUNOS4
- X
- X
- X# ---------------------------------------------------------------
- X# Any number of the following options can be enabled
- X# ---------------------------------------------------------------
- X
- X# Use syslog(3) for recording password changes and errors
- XSYSLOG = -DSYSLOG
- X
- X# Use private version of getpass(3) which is better behaved than
- X# the version in libc (at least the 4.3BSD version).
- XGETPASS = -DXGETPASS
- X
- X
- X# -DXPUTPWENT provides putpwent() if not in libc.
- X# PUTPWENT = -DXPUTPWENT
- X
- X# -DXFGETPWENT provides fgetpwent() if not in libc.
- X# FGETPWENT = -DXFGETPWENT
- X
- X# ---------------------------------------------------------------
- X# Program building
- X# ---------------------------------------------------------------
- X
- X# Debugging switches
- XDEBUG = -g -DDEBUG
- X
- X# 'XFLAGS' are the configuration flags exported to sub-makes.
- X# Change '-O' in XFLAGS to $(DEBUG) for development work,
- X# change to '-g' to use source debugger.
- XXFLAGS = -O $(BSD) $(SYS5) $(SUNOS) $(ULTRIX)
- X
- X# 'CFLAGS' are the flags for npasswd only
- XCFLAGS = $(XFLAGS) $(SYSLOG) $(GETPASS) $(PUTPWENT) $(FGETPWENT) \
- X $(HFD) $(CFD) $(MFD) $(PWFD) $(PWTD) $(PWSD)
- X
- X# Change the following line to $(DEBUG) for debugging
- XLDFLAGS =
- X
- X# ---------------------------------------------------------------
- X# Start of make rules
- X# ---------------------------------------------------------------
- X#
- X# Remove the leading comment of ONE of the following entries
- X# for 'all'
- X#
- X# all: yp_passwd # Build YP version
- X# all: pw_passwd # Build standard version
- X# all: ui_passwd # Build UT CC userinfo version
- X
- Xfirst::
- X -@echo Do \"make yp_passwd\" to build YP/NIS version.
- X -@echo Do \"make pw_passwd\" to build standard version.
- X -@echo
- X -@echo You should also edit this Makefile to pick the
- X -@echo target for 'all' and configure npasswd for your system.
- X
- X# ---------------------------------------------------------------
- X# Standard password file version
- X# ---------------------------------------------------------------
- XOBJ_PW = npasswd.o pw_passwd.o $(CHKLIB)
- X
- Xpw_passwd: $(OBJ_PW)
- X $(CC) -o $(PASSWD) $(LDFLAGS) $(OBJ_PW)
- X
- X# ---------------------------------------------------------------
- X# Yellow Pages version
- X# ---------------------------------------------------------------
- XOBJ_YP = npasswd.o pw_yp.o $(CHKLIB)
- X
- Xyp_passwd: $(OBJ_YP)
- X $(CC) -o $(PASSWD) $(LDFLAGS) $(OBJ_YP) $(LIB_RPCSVC)
- X
- X# ---------------------------------------------------------------
- X# UTEXAS CC database version
- X# ---------------------------------------------------------------
- XOBJ_UI = npasswd.o pw_userinfo.o $(CHKLIB)
- X
- Xui_passwd: $(OBJ_UI)
- X $(CC) -o $(PASSWD) $(LDFLAGS) $(OBJ_UI) -luserinfo
- X
- X# ---------------------------------------------------------------
- X# Make password checker library
- X# ---------------------------------------------------------------
- X$(CHKLIB):
- X cd checkpasswd; \
- X make $(MFLAGS) "CFLAGS=$(XFLAGS)" $(CHECKPW_FLAGS) checkpasswd.a
- X
- X
- X# ---------------------------------------------------------------
- X# Misc stuff
- X# ---------------------------------------------------------------
- Xclean::
- X -rm -f *.o a.out n*passwd core
- X -rm -f passwd passwd.dir passwd.pag opasswd
- X -for f in $(SUBDIRS); do \
- X (cd $$f; make clean); done
- X
- X# ---------------------------------------------------------------
- Xinstall: $(PASSWD)
- X @if [ `whoami` != root ]; then\
- X echo Must be super-user to install; \
- X exit 1; \
- X else \
- X exit 0; \
- X fi
- X install -s -m $(IMODE) $(PASSWD) $(DEST)$(BINDIR)/$(PASSWD)
- X @if [ ! -r $(CF) ]; then\
- X echo install -c -m 0644 npasswd.conf $(CF);\
- X install -c -m 0644 npasswd.conf $(CF);\
- X else \
- X echo $(CF) already exists.. edit to change; fi
- X @if [ ! -r $(HF) ]; then\
- X echo install -c -m 0644 npasswd.help $(HF);\
- X install -c -m 0644 npasswd.help $(HF);\
- X else \
- X echo $(HF) already exists.. edit to change; fi
- X @echo Put site-specific information in $(MF)
- X
- Xinstall.man::
- X @echo Customize a manual page
- X# install -c -m 0444 npasswd.1 $(DEST)$(MANDIR)
- X
- X# ---------------------------------------------------------------
- X# Make copy of password file for testing
- Xsetup::
- X -rm -f passwd passwd.dir passwd.pag passwd.old
- X cp /etc/passwd passwd
- X -if [ -f /etc/mkpasswd ]; then \
- X /etc/mkpasswd passwd; fi
- X
- X# ---------------------------------------------------------------
- Xdist::
- X @stuff/makedist $(DISTNAME)
- X
- X# ---------------------------------------------------------------
- X#
- X# Source dependancies
- X#
- Xnpasswd.o: npasswd.c version.h
- Xpw_passwd.o: pw_passwd.c
- Xpw_yp.o: pw_yp.c
- Xpw_userinfo.o: pw_userinfo.c
- X
- X# End Makefile.dist
- END_OF_FILE
- if test 7149 -ne `wc -c <'Makefile.dist'`; then
- echo shar: \"'Makefile.dist'\" unpacked with wrong size!
- fi
- # end of 'Makefile.dist'
- fi
- if test -f 'checkpasswd/README' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'checkpasswd/README'\"
- else
- echo shar: Extracting \"'checkpasswd/README'\" \(6143 characters\)
- sed "s/^X//" >'checkpasswd/README' <<'END_OF_FILE'
- XREADME for checkpasswd
- X
- X @(#)README 1.1 5/18/89
- X
- X** NOTE **
- XOriginally the 'mdbm' library was to be distributed along with this program,
- Xbut license problems have led to its removal. There are hooks in some of the
- Xcode for "MDBM". Should I locate with a public domain DBM workalike,
- Xthose hooks will be reworked to use it and it will be distributed.
- X
- X* Why this code...
- X
- XThe infamous Internet worm of November 1988 used among its attacks
- Xa password guesser. It is frightening how many passwords on how many UNIX
- Xsystems were guessed by this algorithim. With the publication of various
- Xpapers about the internals of the worm, the password cracking algorithims
- Xcame to light.
- X
- XI replicated the worm password cracker from those papers, ran it
- Xagainst my password file and got too many hits to be comfortable.
- XI decided that some more rigourous validity checking was needed for passwords.
- X
- XSo I took the worm algorithim and rewrote it into a password checker.
- X
- XA previous version of this code has appeared on comp.sources.misc.
- X
- X* What this code does...
- X
- XThe sequence of checks done is:
- X
- X 1. Enforcement of a minimal length.
- X
- X 2. Simple 'lexical' checks to catch some dumb passwords, such as
- X repeats of the same letter (e.g. 'aaa'). Strange characters
- X are also checked for.
- X
- X 3. Password is compared against some host-specific information, such as
- X the hostname.
- X
- X 4. Password is checked against a number of permutations on the users'
- X passwd information (login name reversed, login name duplicated).
- X
- X 5. Password is checked against the user's FINGER information.
- X
- X 6. A list of dictionaries are scanned for the password.
- X
- XAll string comparsions are case-independant.
- X
- XWhat kinds of passwords will be accepted:
- X Passwords which use mixed upper and lower case.
- X Passwords which use punctuation characters.
- X Passwords which use numbers.
- X Passwords which use allowed control characters.
- X
- XBy default, the following control characters are NOT allowed in passwords:
- X control-c control-d control-h control-j control-m
- X control-o control-r control-s control-q control-y
- X control-z control-\ control-[ control-] DELETE
- X
- XThese are typical tty special characters on UCB-derived UNIX systems.
- XA user could put these characters in their password by quoting them
- Xwith control-v, but there is no guarantee that the tty modes
- Xset by login(1) would allow them to be properly entered, so they
- Xare best avoided.
- X
- XThis table may be replaced or supplimented via the configuration file.
- X
- X* About checkpasswd....
- X
- XThe checking routine is table driven (in checkpasswd.c) so that new routines
- Xcan be added easily.
- X
- XI did not use some other password check routines that have been made available
- Xbecause they rejected many passwords which I thought was reasonable. These
- Xchecks are concerned with filtering out words that might be easily guessed.
- XI believe that my tests, especially the dictionary lookup, perform this
- Xfunction. Checks can be inserted or deleted as desired.
- X
- XThis version is much more functional and configurable that the original
- Xsubroutine package provided. I chose to convert the subroutine to a
- Xstandalone program that is self-contained and can be executed from other
- Xprograms.
- X
- XVery soon afterwards I realized that the standalone program could be
- Xrefitted to work as a library. So checkpasswd comes in two forms:
- Xstandalone and library.
- X
- XThe standalone program reads from standard input and reports
- Xto standard output.
- X
- XThe library version can be called from a program and will return
- X1 or 0 depending on whether the password should be used. It will
- Xalso print a diagnostic message to stdout if it does not deem the password
- Xto be desirable.
- X
- XThe routine setcheckpasswd() can be used to set options when using the library.
- XSee checkpasswd(3) about setting options.
- X
- X* Dictionaries...
- X
- XI figured that why no password checker to date did dictionary lookups is
- Xbecause of the overhead in doing so. I use a DBM database version of
- Xa dictionary to make the lookups fast. On my system, the DBM version of
- X/usr/dict/words takes up only about 800K - worth the space to make
- Xpassword checking fast.
- X
- XSince multiple dictionaries can be searched, any new words that you want
- Xto 'take out' of use can be added to one of them. As an aside, this
- Xis why I just couldn't use the vanilla V7 dbm - it can not handle more
- Xthan one database.
- X
- XThe reason for the dictionary checking is to thwart crackers who go through
- Xthe system dictionary looking for passwords. If we prevent people from
- Xchoosing passwords which are in publicly readable dictionaries, that
- Xcracking strategy should then fail.
- X
- XPasswords which use punctuation or control characters or have multiple
- Xchanges of case are not looked up. Since these would not be found in the
- Xspelling dictionary, there is no reason to look for them.
- X
- X*** Important note ***
- XIt is a good idea to have dictionary data bases because if egrep(1)
- Xhas to be used to search an ASCII file, its arguments are prey to being
- Xread with ps(1).
- X
- X* How to use checkpasswd...
- X
- XThe standalone checkpasswd is not designed to be an end-user program.
- XIt should be installed in a library directory somewhere and used from
- Xanother program. The -o, -s and -e options are provided to facilitate
- Xsuch use, and the 'call_ckpasswd.c' module included shows an example of this.
- X
- X* To do...
- X
- XProvide some way to pass an encrypted password on the command line.
- XClose the window of vunerablity on egrep argument sniffing.
- X
- X* Administrativa...
- X
- XI have done considerable testing but do not guarantee that this program
- Xis bullet-proof.
- X
- XThere is no copyright on this version of checkpasswd.
- X
- X* Building checkpasswd...
- X
- X1. Edit Makefile and select which DBM method to use and where to install
- X checkpasswd and config file
- X2. Edit dict/Makefile and select which DBM method to use.
- X3. Do a 'make all'.
- X4. Use dict/makedict to build DBM dictionaries.
- X
- X** If you are not using the standalone application version, stop now **
- X
- X5. Edit checkpasswd.cf to reflect your preferences.
- X6. Do a 'make install'.
- X
- X> Bugs & enhancements...
- X
- XSend bug report & enhancements to:
- X clyde@emx.utexas.edu
- X or
- X uunet!cs.utexas.edu!ut-emx!clyde
- X
- END_OF_FILE
- if test 6143 -ne `wc -c <'checkpasswd/README'`; then
- echo shar: \"'checkpasswd/README'\" unpacked with wrong size!
- fi
- # end of 'checkpasswd/README'
- fi
- if test -f 'checkpasswd/checkpasswd.8' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'checkpasswd/checkpasswd.8'\"
- else
- echo shar: Extracting \"'checkpasswd/checkpasswd.8'\" \(5705 characters\)
- sed "s/^X//" >'checkpasswd/checkpasswd.8' <<'END_OF_FILE'
- X'\"
- X'\" @(#)checkpasswd.8 1.1 5/18/89 (cc.utexas.edu) /home/emx/u2/cc/clyde/src/new/passwd/checkpasswd/SCCS/s.checkpasswd.8
- X'\"
- X.TH CHECKPASSWD 8
- X.SH NAME
- Xcheckpasswd \- check passwords
- X.SH SYNOPSIS
- X.B checkpasswd
- X[
- X.B \-\^c
- Xconfig_file ] [
- X.B \-\^e
- X] [
- X.B \-\^o
- X] [
- X.B \-\^s
- X] [
- X.B \-\^u
- Xuser id ] [
- X.B \-\^V
- X] [
- X.B \-\^?
- X]
- X.SH DESCRIPTION
- X.I Checkpasswd
- Xreads passwords from the standard input and subjects them to suitablity tests.
- XThese tests are detailed below.
- XIt purposely does
- X.B not
- Xtake a password argument since process
- Xarguments are not secure on most UNIX systems - they can be printed by
- X.IR ps (1).
- X.PP
- X.I Checkpasswd
- Xis not meant as a replacement for
- X.IR passwd (1)
- Xand so does not suppress character echo while reading passwords.
- XThe standard input can be redirected from a pipe or file, which facilitates
- Xit being called from another program such as
- X.IR passwd (1).
- X.PP
- X.I Checkpasswd
- Xexits with the check status for the most recent password entered.
- XThe check status is one of the following:
- X.nf
- X-1 A serious error occured.
- X0 The password passed all checks.
- X1 The password was a null string.
- X2 The password was \'too easy\' to guess.
- X3 The password was part of the users \'\fIfinger\fP\' information.
- X4 The password was found in a dictionary search.
- X5 The password contained an illegal character or sequence.
- X6 The password was too short.
- X.fi
- X.PP
- XIn addition to the check status, an informative message is printed to
- Xthe standard output (unless supressed).
- X.PP
- XThe options available are:
- X.TP
- X.B \-\^c
- XTake the next argument as the configuration file to read.
- XSee the CONFIGURATION section for information on the configuration file.
- X.TP
- X.B \-\^e
- XPrint the check status in numeric form as well as the informative message.
- XThis is useful for programs which want to process the output from
- X.IR checkpasswd .
- X.TP
- X.B \-\^o
- XTest one password only and exit with check status.
- X.TP
- X.B \-\^s
- XSupress output of informative messages.
- X.TP
- X.B \-\^u
- XTake the next argument as the user id (in numeric form) to use for password
- Xfile data checking.
- XThis option is restricted to the super-user.
- X.TP
- X.B \-\^V
- XPrint version information.
- X.TP
- X.B \-\^?
- XPrint help message.
- X.SH "CHECKS PERFORMED"
- X.PP
- X.I Checkpasswd
- Xperforms the following tests on each password:
- X.IP 1.
- XLength is checked to see if it is within bounds.
- XPasswords which are too short are rejected, while passwords that are
- X\'too long\' are passed but a warning message issued.
- X.IP 2.
- XThe password is scanned for illegal characters and character combinations,
- Xsuch as runs of the same character (e.g. \'aaa\').
- XPasswords that do not use upper and lower case alphabetics will be rejected
- Xunless otherwise specified via the configuration file.
- X.IP 3.
- XThe password is checked against various per-site information, such as the
- Xhost name.
- X.IP 4.
- XThe password is checked against the
- X.IR passwd (5)
- Xinformation for the user.
- XThe password is compared against a number of permutations of this data.
- X.IP 5.
- XThe password is checked against the user\'s \'finger\' information.
- X.IP 6.
- XThe password is search for in a list of dictionaries and is rejected if it
- Xis found in any of them.
- X.SH CONFIGURATION
- X.PP
- XMany of the criteria used by
- X.I checkpasswd
- Xcan be set via a configuration file.
- XThe default configuration file is
- X.BR /usr/adm/checkpasswd.cf .
- X.PP
- XLines in the configuration file which start with '#' ignored.
- XItems in \'[ ]\' are optional, the default value is in \'{ }\'.
- X.sp
- X.nf
- X\fBdictionary\fP /path/to/dictionary [description of dictionary]
- X.fi
- X.RS
- XSpecifies a dictionary to look in.
- XIf there is a DBM data base version of the dictionary, that will be used,
- Xelse
- X.IR egrep
- Xwill be used on the file.
- XThere may be multiple
- X.B dictionary
- Xdirectives in the configuration file, and they will be searched in
- Xthe order given.
- XA list of default dictionaries may be built into
- X.IR checkpasswd .
- X.br
- XThe
- X.I makedict
- Xprogram can be used to build DBM dictionaries, and
- X.I viewdict
- Xused to review them.
- X.RE
- X.sp
- X.nf
- X\fBsinglecase\fP yes | {no}
- X.fi
- X.RS
- XSpecifies whether or not single-case passwords are legal.
- XThe default is to reject single-case passwords.
- X.RE
- X.sp
- X.nf
- X\fBminlength\fP N {5}
- X.fi
- X.RS
- XSpecifies the minimum password length to accept.
- XPasswords shorter that this will not be accepted.
- X.RE
- X.sp
- X.nf
- X\fBmaxlength\fP N {8}
- X.fi
- X.RS
- XSpecifies the maximum effective password length.
- XThis does not affect acceptance of a password.
- XThe
- X.IR crypt (3)
- Xroutine usually encrypts only the first 8 characters of a string due to the
- Xalgorithim used.
- XIf the password is longer than this, a warning message is printed to inform the
- Xuser that not the entire password will be used.
- X.RE
- X.sp
- X.nf
- X\fBprintonly\fP yes | {no}
- X.fi
- X.RS
- XSpecifies that only printable ASCII characters are to be allowed in passwords.
- XUse of control characters should be encouraged but may cause problems on
- Xsome systems.
- X.RE
- X.sp
- X.nf
- X\fBbadchars\fP "list-of-characters"
- X.br
- X\fBbadchars\fP +"list-of-characters"
- X.fi
- X.RS
- XSpecifies a list of characters which are not allowed in passwords.
- XThe first form replaces the illegal character table.
- XThe second form adds to the illegal character table.
- XCharacters may be given in the following forms:
- X.br
- X.ti +.25i
- XC special character escapes (e.g. \\\|t )
- X.br
- X.ti +.25i
- X\\\|0[0\-7] (e.g. \\\|013)
- X.br
- X.ti +.25i
- X\\\|0x[0\-9\| \|a\-f] (e.g. \\\|0xa)
- X.br
- X.ti +.25i
- X^[a\-z\|,\|A\-Z\|,\|[\|,\|\\\|,\|]\|,\|^\|,\|-] (e.g.,^c)
- X.br
- X.sp
- XThe default content of the illegal characters table is a collection
- Xof terminal special characters.
- X.RE
- X.in 0
- X.SH SEE ALSO
- Xmakedict, viewdict, passwd(1)
- X.SH AUTHOR
- XClyde Hoover
- X.br
- XComputation Center
- X.br
- XThe University of Texas at Austin
- X.br
- XAustin, Texas
- X.br
- Xclyde@emx.utexas.edu, uunet!cs.utexas.edu!ut-emx!clyde
- X.PP
- END_OF_FILE
- if test 5705 -ne `wc -c <'checkpasswd/checkpasswd.8'`; then
- echo shar: \"'checkpasswd/checkpasswd.8'\" unpacked with wrong size!
- fi
- # end of 'checkpasswd/checkpasswd.8'
- fi
- if test -f 'checkpasswd/pwck_dict.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'checkpasswd/pwck_dict.c'\"
- else
- echo shar: Extracting \"'checkpasswd/pwck_dict.c'\" \(4785 characters\)
- sed "s/^X//" >'checkpasswd/pwck_dict.c' <<'END_OF_FILE'
- X
- X/* -------------------------------------------------------------------- */
- X/* */
- X/* Author: Clyde Hoover */
- X/* Computation Center */
- X/* The University of Texas at Austin */
- X/* Austin, Texas 78712 */
- X/* clyde@emx.utexas.edu */
- X/* uunet!cs.utexas.edu!ut-emx!clyde */
- X/* */
- X/*This code may be distributed freely, provided this notice is retained. */
- X/* */
- X/* -------------------------------------------------------------------- */
- X/*
- X * pwck_dictionary - Look in the forbidden password dictionaries.
- X * Returns:
- X * PWCK_INDICT if <password> was in any dictionary
- X * PWCK_OK if not
- X */
- X
- X#ifndef lint
- Xstatic char sccsid[] = "@(#)pwck_dict.c 1.2 11/26/90 (cc.utexas.edu)";
- X#endif
- X
- X#include "checkpasswd.h"
- X
- Xdictionary *dictionaries = 0; /* List of dictionaries */
- Xstatic char *egrep = "PATH=/bin:/usr/bin:/usr/ucb; egrep -s"; /* egrep */
- X
- Xpwck_dictionary(password, userid, mesgbuf)
- Xchar *password; /* Password to check */
- Xint userid; /* NOTUSED */
- Xchar *mesgbuf; /* Message buffer */
- X{
- X int rcode; /* Return code temp */
- X char *p; /* Scratch */
- X dictionary *d; /* Current dictionary */
- X
- X /*
- X * If there are any non-alpha characters
- X * don't bother with the dictionary checks.
- X */
- X for (p = password; *p; p++) {
- X if (!isalpha(*p))
- X return(PWCK_OK);
- X }
- X#ifdef DEBUG
- X printf("pwck_dictionary: \"%s\"\n", password);
- X#endif
- X for (d = dictionaries; d; d = d->dict_next) {
- X#ifdef DEBUG
- X printf("\tdictionary '%s'\n", d->dict_path);
- X#endif
- X if ((rcode = InDictionary(d->dict_path, password)) != PWCK_OK){
- X (void) sprintf(mesgbuf,
- X "Password found in dictionary '%s'",
- X d->dict_path);
- X return(rcode);
- X }
- X }
- X return(PWCK_OK);
- X}
- X
- X#ifdef MDBM
- X/*
- X * Use the 'mdbm' package by Chris Torek and others
- X */
- X#include "mdbm.h"
- X#define DBM struct mdbm
- X#define DBM_FETCH mdbm_fetch
- X#define DBM_CLOSE mdbm_close
- X#endif
- X
- X/*
- X * Using the 4.3BSD 'ndbm' routines
- X */
- X#ifdef NDBM
- X#include <ndbm.h>
- X#define DBM_FETCH dbm_fetch
- X#define DBM_CLOSE dbm_close
- X#endif
- X
- X/*
- X * InDictionary - look for <password> in <dictionary>
- X *
- X * Look in a DBM version of the dictionary if present,
- X * else use egrep to search the flat file.
- X *
- X * Look for <password>, then if the first letter
- X * is capitalized, force to lower and look again. I don't care
- X * if <password> is in the dictionary but has mixed case letters.
- X * BUT if the first letter has been capitalized, I care because
- X * that's not a sufficent permutation to be secure.
- X *
- X * If more than the first letter is capitalized, then the dictionary
- X * lookup will fail.
- X *
- X * Returns:
- X * PWCK_INDICT if <password> was found in <dictionary>
- X * PWCK_OK if not
- X */
- Xstatic
- XInDictionary(which_dictionary, password)
- Xchar *which_dictionary, /* Pathname of dictionary */
- X *password; /* Plaintext of password */
- X{
- X#if defined(NDBM) || defined(MDBM)
- X DBM *dbp; /* DBM database pointer */
- X datum k, /* DBM lookup key */
- X d; /* DBM lookup datum */
- X#endif
- X int uc = isupper(password[0]); /* Is first char UC? */
- X char pwtemp[BUFSIZ]; /* Scratch buffer */
- X#ifdef MDBM
- X if ((dbp = mdbm_open(which_dictionary, 0, 0,
- X (int *)0, (int *)0, (char *)0)) == (DBM *)0)
- X#endif
- X#ifdef NDBM
- X if ((dbp = dbm_open(which_dictionary, 0, 0)) == (DBM *)0)
- X#endif
- X {
- X char command[BUFSIZ]; /* Command build buffer */
- X int rc; /* Return code from sytem(3) */
- X
- X if ((rc = open(which_dictionary, 0)) < 0)
- X return(PWCK_OK);
- X (void) close(rc);
- X /*
- X * If the first letter is capitalized, look for
- X * "[wW]ord" else look for "word"
- X */
- X if (uc)
- X (void) sprintf(command,
- X "%s '^[%c%c]%s$' %s > /dev/null",
- X egrep, password[0], password[0] | 040,
- X &password[1], which_dictionary);
- X else
- X (void) sprintf(command, "%s '^%s$' %s > /dev/null",
- X egrep, password, which_dictionary);
- X rc = system(command);
- X if (rc == 0)
- X return(PWCK_INDICT);
- X else
- X return(PWCK_OK);
- X }
- X#if defined(NDBM) || defined(MDBM)
- X#define returnwith(code) { DBM_CLOSE(dbp); return(code); }
- X /*
- X * Look in the DBM version of the dictionary.
- X */
- X (void) strcpy(pwtemp, password);
- X k.dptr = pwtemp;
- X k.dsize = strlen(pwtemp);
- X d = DBM_FETCH(dbp, k);
- X if (d.dptr)
- X returnwith(PWCK_INDICT);
- X if (uc) {
- X pwtemp[0] |= 040;
- X d = DBM_FETCH(dbp, k);
- X if (d.dptr)
- X returnwith(PWCK_INDICT);
- X }
- X returnwith(PWCK_OK);
- X#endif /* defined(NDBM) || defined(MDBM) */
- X}
- X/* End pwck_dict.c */
- END_OF_FILE
- if test 4785 -ne `wc -c <'checkpasswd/pwck_dict.c'`; then
- echo shar: \"'checkpasswd/pwck_dict.c'\" unpacked with wrong size!
- fi
- # end of 'checkpasswd/pwck_dict.c'
- fi
- if test -f 'checkpasswd/pwck_lexical.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'checkpasswd/pwck_lexical.c'\"
- else
- echo shar: Extracting \"'checkpasswd/pwck_lexical.c'\" \(4195 characters\)
- sed "s/^X//" >'checkpasswd/pwck_lexical.c' <<'END_OF_FILE'
- X
- X/* -------------------------------------------------------------------- */
- X/* */
- X/* Author: Clyde Hoover */
- X/* Computation Center */
- X/* The University of Texas at Austin */
- X/* Austin, Texas 78712 */
- X/* clyde@emx.utexas.edu */
- X/* uunet!cs.utexas.edu!ut-emx!clyde */
- X/* */
- X/*This code may be distributed freely, provided this notice is retained. */
- X/* */
- X/* -------------------------------------------------------------------- */
- X/*
- X * pwck_lexical - Perform lexical analysis of password candidate.
- X *
- X * Things which are ok:
- X * Mixed case
- X * Digits
- X * Punctutation
- X * Control characters (except for those in the forbidden table)
- X *
- X * Things which are NOT ok:
- X * Passwords less than 'min_length' characters
- X * Runs of more than <run_length> of the same character
- X * (e.g. 'zzz')
- X * Single-case strings (selectable via the config file)
- X *
- X * Things NOT checked for:
- X * Cycles of character groups (e.g. 'aabbcc' or 'ababab')
- X * Sequential characters 'abcdef' or '123456'
- X */
- X
- X#ifndef lint
- Xstatic char sccsid[] = "@(#)pwck_lexical.c 1.3 11/7/89 (cc.utexas.edu)";
- X#endif
- X
- X#include "checkpasswd.h"
- X
- X#define P_U 0x1 /* Upper case in password */
- X#define P_L 0x2 /* Lower case in password */
- X#define P_C 0x4 /* Control chars in password */
- X#define P_D 0x8 /* Digits in password */
- X#define P_P 0x10 /* Punctutation chars in password */
- X
- X#define hasone(P) (what |= (P))
- X#define hasany(P) ((what & (P)) == (P))
- X
- Xpwck_lexical(password, userid, mesg)
- Xchar *password; /* Password to check */
- Xint userid; /* NOTUSED */
- Xchar *mesg; /* Message buffer */
- X{
- X int rc; /* Duplicate character run count */
- X char *p = password; /* Scratch */
- X char what = 0, /* Lexical analysis result flags */
- X last = 0; /* Last character seen (for run checks) */
- X
- X mesg[0] = 0;
- X#ifdef DEBUG
- X printf("pwck_lexical: \"%s\"\n", password);
- X#endif
- X rc = strlen(password);
- X if (min_length && rc < min_length)
- X return(PWCK_SHORT);
- X /*
- X * Only the first <max_length> characters of a password are actually
- X * used due to the limitations of crypt(3). If the given
- X * password is longer than this, issue warning message.
- X */
- X if (max_length && rc > max_length) {
- X printf("WARNING: Only the first %d characters of this password will be used \n",
- X max_length);
- X }
- X
- X for (p = password; *p; p++) {
- X if (*p != last) {
- X last = *p;
- X rc = 1;
- X }
- X else { /* Run of same characters */
- X if (run_length && ++rc >= run_length) {
- X (void) sprintf(mesg,
- X "This password has %d or more repeated characters",
- X run_length);
- X return(PWCK_OBVIOUS);
- X }
- X }
- X if (*p < ' ' || *p > '~') { /* Non-printing character */
- X char *_ctran();
- X
- X if (print_only) {
- X (void) strcpy(mesg,
- X "This password has non-printing characters");
- X return(PWCK_ILLCHAR);
- X }
- X if (index(illegalcc, *p)) {
- X (void) sprintf(mesg,
- X "Illegal character '%s' in this password",
- X _ctran(*p));
- X return(PWCK_ILLCHAR);
- X }
- X hasone(P_C);
- X }
- X else if (isupper(*p)) hasone(P_U);
- X else if (islower(*p)) hasone(P_L);
- X else if (ispunct(*p)) hasone(P_P);
- X else if (isdigit(*p)) hasone(P_D);
- X }
- X if (hasany(P_U | P_L)) return(PWCK_OK); /* UC+lc */
- X if (hasany(P_D)) return(PWCK_OK); /* Numbers */
- X if (hasany(P_P)) return(PWCK_OK); /* Punctutation chars */
- X if (hasany(P_C)) return(PWCK_OK); /* Control chars */
- X /*
- X * Check for mono-case passwords
- X */
- X if (!hasany(P_U) && single_case) /* All lower case alpha */
- X return(PWCK_OK);
- X if (!hasany(P_L) && single_case) /* All upper case alpha */
- X return(PWCK_OK);
- X
- X if (!hasany(P_L))
- X (void) strcpy(mesg,
- X "Upper-case only passwords not allowed");
- X if (!hasany(P_U))
- X (void) strcpy(mesg,
- X "Lower-case only passwords not allowed");
- X return(PWCK_ILLCHAR);
- X}
- X/* End pwck_lexical.c */
- END_OF_FILE
- if test 4195 -ne `wc -c <'checkpasswd/pwck_lexical.c'`; then
- echo shar: \"'checkpasswd/pwck_lexical.c'\" unpacked with wrong size!
- fi
- # end of 'checkpasswd/pwck_lexical.c'
- fi
- if test -f 'pw_passwd.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'pw_passwd.c'\"
- else
- echo shar: Extracting \"'pw_passwd.c'\" \(9416 characters\)
- sed "s/^X//" >'pw_passwd.c' <<'END_OF_FILE'
- X
- X/* -------------------------------------------------------------------- */
- X/* */
- X/* Author: Clyde Hoover */
- X/* Computation Center */
- X/* The University of Texas at Austin */
- X/* Austin, Texas 78712 */
- X/* clyde@emx.utexas.edu */
- X/* uunet!cs.utexas.edu!ut-emx!clyde */
- X/* */
- X/*This code may be distributed freely, provided this notice is retained. */
- X/* */
- X/* -------------------------------------------------------------------- */
- X/*
- X * pw_passwd - Routines for dealing with password files.
- X * Handles V7 / *.* BSD / Sys V format.
- X */
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <signal.h>
- X#include <errno.h>
- X#include <pwd.h>
- X#include <fcntl.h>
- X
- X#ifndef lint
- Xstatic char sccsid[] = "@(#)pw_passwd.c 1.9 1/24/91 (cc.utexas.edu)";
- X#endif
- X
- X#define SLOP 128 /* Size difference tolerated old <> new passwd file */
- X
- X#ifdef SYSV
- X/*
- X * System V password aging stuff
- X */
- X#define SEC_PER_WEEK ((long )24 * 7 * 60 * 60)
- X
- Xextern long a64l();
- Xextern char *l64a();
- X
- Xstatic time_t pwage = 0,
- X maxpwtime = 0,
- X minpwtime = 0,
- X now;
- X#endif
- X
- Xtypedef struct passwd passwd;
- Xtypedef struct passwd *passwdp;
- X
- Xstatic passwd theUser, /* The user to change */
- X Me; /* The user who invoked command */
- Xstatic int myuid, /* Uid of program */
- X mytempfile = 0; /* Does PASSWD_TEMP belong to me? */
- X
- X/*
- X * File names
- X */
- X#ifndef PASSWD_FILE
- X#define PASSWD_FILE "/etc/passwd"
- X#endif
- X
- X#ifndef PASSWD_SAVE
- X#define PASSWD_SAVE "/etc/opasswd"
- X#endif
- X
- X#ifndef PASSWD_TEMP
- X#define PASSWD_TEMP "/etc/ptmp"
- X#endif
- X
- X#define PASSWD_MODE 0644
- X
- X#ifdef DEBUG
- Xstatic char *passwdtemp = "./etc_ptmp",
- X *passwdfile = "./etc_passwd",
- X *savefile = "./etc_opasswd";
- X#else
- Xstatic char *passwdtemp = PASSWD_TEMP,
- X *passwdfile = PASSWD_FILE,
- X *savefile = PASSWD_SAVE;
- X#endif
- X
- Xextern int errno;
- X
- Xchar *getlogin(),
- X *crypt();
- X
- X/*
- X * pw_initialize - set up
- X */
- Xpw_initialize()
- X{
- X passwdp me; /* Temp */
- X char *myname = getlogin(); /* Name of invoker */
- X
- X#ifdef DEBUG
- X setpwfile(passwdfile);
- X#endif
- X myuid = getuid();
- X if (myname && *myname) {
- X if ((me = getpwnam(myname)) == NULL)
- X quit(1, "Cannot get user identification from name.\n");
- X } else {
- X if ((me = getpwuid(myuid)) == NULL)
- X quit(1, "Cannot get user identification from uid.\n");
- X }
- X
- X _cppasswd(me, &Me);
- X return(1);
- X}
- X
- X/*
- X * pw_getuserbyname - get password
- X *
- X * Returns 1 if passwd info found for <name>
- X * 0 otherwise
- X */
- Xpw_getuserbyname(name, passwdb)
- Xchar *name, /* User name */
- X *passwdb; /* Where to stuff password */
- X{
- X passwdp p; /* Temp */
- X
- X if ((p = getpwnam(name)) == NULL)
- X return(0);
- X _cppasswd(p, &theUser);
- X (void) strcpy(passwdb, p->pw_passwd);
- X return(1);
- X}
- X
- X/*
- X * pw_permission - check password change permission
- X *
- X * Returns 1 if password can be changed
- X * 0 if not
- X */
- Xpw_permission()
- X{
- X if (strcmp(Me.pw_name, theUser.pw_name) && myuid)
- X return(0);
- X
- X /*
- X * Other checks can be put here to determine if the invoker should
- X * be allowed to change this password.
- X */
- X#ifdef SYSV
- X if (theUser.pw_age) {
- X pwage = a64l(theUser.pw_age);
- X maxpwtime = pwage & 077;
- X minpwtime = (pwage >> 6) & 077;
- X pwage >>= 12;
- X (void) time(&now);
- X now /= SEC_PER_WEEK;
- X if (pwage <= now) {
- X if (myuid && (now < (pwage + minpwtime))) {
- X fprintf(stderr,
- X "Sorry: < %ld weeks since last change\n",
- X minpwtime);
- X return(0);
- X }
- X if ((minpwtime > maxpwtime) && myuid) {
- X fprintf(stderr,
- X "You may not change this password.\n");
- X return(0);
- X }
- X }
- X }
- X#endif
- X return(1);
- X}
- X
- X/*
- X * pw_compare - compare old and new passwords
- X *
- X * Returns 1 if check = new, 0 if not
- X */
- Xpw_compare(current, check)
- Xchar *current, /* Current pw (encrypted) */
- X *check; /* check pw (plain) */
- X{
- X if (!*current)
- X return(0);
- X return(!strcmp(current, crypt(check, current)));
- X}
- X
- X/*
- X * pw_check - sanity check password. Right now just calls
- X * the password check program
- X *
- X * Returns 1 if password is ok to use, 0 otherwise
- X */
- Xpw_check(newpw)
- Xchar *newpw; /* New password (plain) */
- X{
- X /* Put other administrative checks here */
- X return(checkpasswd(theUser.pw_uid, newpw));
- X}
- X
- X/*
- X * pw_replace - replace password in passwd file
- X */
- Xpw_replace(newpwd, curpwd)
- Xchar *newpwd, /* New password (plain) */
- X *curpwd; /* Old password (plain) */
- X{
- X#ifdef SYSV
- X int (*sigint)(), /* Save SIGINT */
- X (*sigquit)(); /* Save SIGQUIT */
- X#else
- X long oldsigs, /* Signal mask save */
- X blocksigs = sigmask(SIGINT) | /* Signals to block */
- X sigmask(SIGQUIT) | /* while updating */
- X sigmask(SIGTSTP); /* password file */
- X#endif
- X passwdp px; /* Temp */
- X char salt[4]; /* Encryption salt */
- X FILE *tf; /* File ptr to new passwd file */
- X int fd; /* File desc. to new passwd file */
- X struct stat oldstat, /* Stat of current passwd file */
- X newstat; /* Stat of new passwd file */
- X
- X /*
- X * Prepare password entry 'theUser' for replacement
- X */
- X randomstring(salt, sizeof(salt));
- X theUser.pw_passwd = crypt(newpwd, salt);
- X#ifdef SYSV
- X /*
- X * Update password age field
- X */
- X if (theUser.pw_age) {
- X if (maxpwtime == 0)
- X *theUser.pw_age = '\0';
- X else {
- X now = time((time_t *)0) / SEC_PER_WEEK;
- X pwage = maxpwtime
- X + (minpwtime << 6)
- X + (now << 12);
- X theUser.pw_age = l64a(pwage);
- X }
- X }
- X#endif
- X (void) umask(0);
- X (void) stat(passwdfile, &oldstat);
- X fd = open(passwdtemp, O_WRONLY|O_CREAT|O_EXCL, PASSWD_MODE);
- X if (fd < 0) {
- X if (errno == EEXIST)
- X quit(0, "Password file busy - try again.\n");
- X perror("Tempfile create");
- X quit(1, "Cannot create temp file.\n");
- X }
- X mytempfile = 1;
- X if ((tf = fdopen(fd, "w")) == NULL)
- X quit(1, "Cannot fdopen temp file.");
- X#ifdef SYSV
- X sigint = signal(SIGINT, SIG_IGN);
- X sigquit = signal(SIGQUIT, SIG_IGN);
- X#else
- X oldsigs = sigblock(blocksigs);
- X#endif
- X setpwent();
- X while ((px = getpwent()) != NULL) {
- X if (px->pw_name == 0 || px->pw_name[0] == 0) /* Sanity check */
- X continue;
- X if (strcmp(px->pw_name, theUser.pw_name) == 0)
- X px = &theUser;
- X (void) putpwent(px, tf);
- X }
- X endpwent();
- X (void) fflush(tf);
- X (void) fstat(fileno(tf), &newstat);
- X (void) fclose(tf);
- X /*
- X * Check if the new password file is complete. Since the encrypted
- X * password is of a fixed length, the new file should be roughly
- X * the same size as the old one.
- X */
- X if (newstat.st_size < (oldstat.st_size - SLOP))
- X quit(1, "New password file appears to be incomplete - aborting.\n");
- X
- X if (rename(passwdfile, savefile) < 0) {
- X perror("Password file save");
- X unlink(passwdtemp);
- X quit(1, "Can't save password file");
- X }
- X if (rename(passwdtemp, passwdfile) < 0) {
- X perror("Password file replace");
- X (void) unlink(passwdtemp);
- X (void) link(savefile, passwdfile);
- X quit(1, "Can't replace password file");
- X }
- X#ifdef BSD4_3
- X updatedbm();
- X#endif
- X#ifdef SYSV
- X (void) signal(SIGINT, sigint);
- X (void) signal(SIGQUIT, sigquit);
- X#else
- X (void) sigsetmask(oldsigs);
- X#endif
- X}
- X
- X/*
- X * pw_cleanup - clean up after myself
- X */
- Xpw_cleanup(code)
- Xint code; /* 0 for normal, 1 for abort */ /*NOTUSED*/
- X{
- X if (mytempfile)
- X (void) unlink(passwdtemp);
- X}
- X
- X/*
- X * _newstr - copy string into new storage
- X */
- Xstatic char *
- X_newstr(s)
- Xchar *s; /* String to copy */
- X{
- X register char *t; /* Temp */
- X char *malloc();
- X
- X if (s == NULL)
- X return(0);
- X t = malloc(strlen(s) + 1);
- X if (t == NULL)
- X quit(1, "No memory.\n");
- X (void) strcpy(t, s);
- X return(t);
- X}
- X
- X/*
- X * _cppasswd - copy a passwd structure
- X */
- Xstatic
- X_cppasswd(f,t)
- Xpasswdp f, /* From */
- X t; /* To */
- X{
- X *t = *f;
- X t->pw_name = _newstr(f->pw_name);
- X#ifdef SYSV
- X t->pw_age = _newstr(f->pw_age);
- X#endif
- X t->pw_passwd = _newstr(f->pw_passwd);
- X t->pw_comment = _newstr(f->pw_comment);
- X t->pw_gecos = _newstr(f->pw_gecos);
- X t->pw_dir = _newstr(f->pw_dir);
- X t->pw_shell = _newstr(f->pw_shell);
- X}
- X
- X#ifdef BSD4_3
- X/*
- X * Update the hashed password data base
- X */
- X#include <ndbm.h>
- X
- X#define SCOPY(S) xp = (S); while (*cp++ = *xp++)
- X#define BCOPY(B) bcopy((char *)&(B), cp, sizeof(int)); cp += sizeof(int)
- X
- Xupdatedbm()
- X{
- X DBM *pwd; /* DBM data base passwd */
- X register char *cp, /* Data storage pointer */
- X *xp; /* String copy pointer */
- X datum key, /* DBM key datum */
- X data; /* DBM data store datum */
- X char buf[512]; /* Data buffer */
- X
- X pwd = dbm_open(passwdfile, O_RDWR, 0);
- X if (pwd == 0)
- X return;
- X cp = buf;
- X /* Pack passwd entry in the form expected by the getpw* routines */
- X SCOPY(theUser.pw_name);
- X SCOPY(theUser.pw_passwd);
- X BCOPY(theUser.pw_uid);
- X BCOPY(theUser.pw_gid);
- X BCOPY(theUser.pw_quota);
- X SCOPY(theUser.pw_comment);
- X SCOPY(theUser.pw_gecos);
- X SCOPY(theUser.pw_dir);
- X SCOPY(theUser.pw_shell);
- X
- X data.dptr = buf;
- X data.dsize = cp - buf;
- X key.dptr = theUser.pw_name;
- X key.dsize = strlen(theUser.pw_name);
- X if (dbm_store(pwd, key, data, DBM_REPLACE) < 0) {
- X perror("dbm_store (name)");
- X quit(1, "Can't store passwd entry (name key).\n");
- X }
- X key.dptr = (char *)&theUser.pw_uid;
- X key.dsize = sizeof (int);
- X if (dbm_store(pwd, key, data, DBM_REPLACE) < 0) {
- X perror("dbm_store (uid)");
- X quit(1, "Can't store passwd entry (uid key).\n");
- X }
- X dbm_close(pwd);
- X}
- X#endif
- END_OF_FILE
- if test 9416 -ne `wc -c <'pw_passwd.c'`; then
- echo shar: \"'pw_passwd.c'\" unpacked with wrong size!
- fi
- # end of 'pw_passwd.c'
- fi
- if test -f 'pw_userinfo.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'pw_userinfo.c'\"
- else
- echo shar: Extracting \"'pw_userinfo.c'\" \(6714 characters\)
- sed "s/^X//" >'pw_userinfo.c' <<'END_OF_FILE'
- X
- X/* -------------------------------------------------------------------- */
- X/* */
- X/* Author: Clyde Hoover */
- X/* Computation Center */
- X/* The University of Texas at Austin */
- X/* Austin, Texas 78712 */
- X/* clyde@emx.utexas.edu */
- X/* uunet!cs.utexas.edu!ut-emx!clyde */
- X/* */
- X/*This code may be distributed freely, provided this notice is retained. */
- X/* */
- X/* -------------------------------------------------------------------- */
- X/*
- X * pw_userinfo.c - UTEXAS CC UNIX User Information Data Base
- X * backend for npasswd
- X */
- X#ifndef lint
- Xstatic char sccsid[] = "@(#)pw_userinfo.c 1.4 8/7/90 (cc.utexas.edu) /tmp_mnt/usr/share/src/private/ut/share/bin/passwd/SCCS/s.pw_userinfo.c";
- X#endif
- X
- X#include <stdio.h>
- X#include <errno.h>
- X#include <syslog.h>
- X#include <strings.h>
- X#include <signal.h>
- X#include <pwd.h>
- X#include <local/userinfo.h>
- X
- Xstatic userdata theUser, /* User having password changed */
- X Me; /* User doing password change */
- X
- X#define P_USER 1
- X#define P_PRIV 2
- X#define P_SU 3
- X
- Xstatic short priv = P_USER; /* Privlege level of <Me> */
- X
- X#define QUOTEC '"' /* Character to start plaintext pwd */
- X#define XPWLEN 3 /* Length of 'original CDC password' */
- X
- Xextern char *getlogin(),
- X *crypt(),
- X *index(),
- X *rindex();
- X
- X/*
- X * pw_initialize - set up
- X */
- Xpw_initialize()
- X{
- X char *myname = getlogin(); /* Login name */
- X struct passwd *pw; /* If getlogin() fails... */
- X userptr u; /* Temp */
- X
- X if (myname == NULL || *myname == '\0') {
- X if ((pw = getpwuid(getuid())) == ((struct passwd *)NULL))
- X quit(1, "Cannot get user name.\n");
- X else
- X myname = pw->pw_name;
- X }
- X bzero((char *)&theUser, sizeof(theUser));
- X bzero((char *)&Me, sizeof(Me));
- X if ((u = getuserbyname(myname)) == NULL)
- X quit(1, "Cannot get user identification.\n");
- X Me = *u;
- X if (Me.ui_priv.p_acct_maint) /* Account maintenance priv? */
- X priv = P_PRIV;
- X if (getuid() == 0) /* SuperUser? */
- X priv = P_SU;
- X}
- X
- X/*
- X * pw_getuserbyname - Get userinfo data by name
- X *
- X * Returns 1 if passwd info found for <name>
- X * 0 otherwise
- X */
- Xpw_getuserbyname(name, passwdb)
- Xchar *name, /* Login name */
- X *passwdb; /* Where to stash password */
- X{
- X userptr u; /* Temp */
- X
- X if ((u = getuserbyname(name)) == NULL)
- X return(0);
- X theUser = *u;
- X (void) strcpy(passwdb, theUser.ui_password);
- X return(1);
- X}
- X
- X/*
- X * pw_permission - check if this user can change this password
- X */
- Xpw_permission()
- X{
- X int mypasswd /* Wanting to change own password? */
- X = (theUser.ui_uid == Me.ui_uid);
- X
- X /*
- X * Must be su to change root password.
- X */
- X if (theUser.ui_uid == 0 && priv != P_SU) {
- X fprintf(stderr, "Permission denied.\n");
- X return(0);
- X }
- X
- X /*
- X * Must be su or have 'account maintenace' capability to change
- X * someone else's password.
- X */
- X if (!mypasswd && priv < P_PRIV) {
- X fprintf(stderr, "Permission denied.\n");
- X return(0);
- X }
- X
- X /*
- X * If 'password change' capability denied, then user cannot
- X * change their own password.
- X */
- X if (theUser.ui_priv.p_nopwchange && mypasswd) {
- X fprintf(stderr, "Permission denied.\n");
- X return(0);
- X }
- X /*
- X * We know at this point that the
- X * invoker does have permission to change the password.
- X */
- X return(1);
- X}
- X
- X/*
- X * pw_compare - compare old and new passwords
- X *
- X * Returns 1 if check = new, 0 if not
- X */
- Xpw_compare(current, check)
- Xchar *current,
- X *check;
- X{
- X if (!*current)
- X return(1);
- X return(strcmp(current, crypt(check, current)) == 0);
- X}
- X
- X/*
- X * pw_check - sanity check password. Performs some site-specific
- X * checks, then calls the checkpasswd() code.
- X *
- X * Returns 1 if password is ok to use, 0 otherwise
- X */
- Xpw_check(new)
- Xchar *new; /* New password (plaintext) */
- X{
- X /* Setting null password? */
- X if (strcmp(new, "@") == 0) {
- X if (theUser.ui_priv.p_null_pass == 0 || priv < P_PRIV) {
- X fprintf(stderr, "Cannot set null password.\n");
- X return(0);
- X }
- X else
- X return(1);
- X }
- X
- X /* A plain text password (enclosed in ""s)? */
- X if (*new == QUOTEC) {
- X char *p = &new[1];
- X
- X while (*p) p++;
- X if (p[-1] == QUOTEC) {
- X if (priv == P_SU) /* Reserved for superuser */
- X return(1);
- X else {
- X fprintf(stderr,
- X "Cannot set plaintext password.\n");
- X return(0);
- X }
- X }
- X }
- X
- X /* Special password (reserved for superuser) */
- X if (strlen(new) == XPWLEN && priv == P_SU)
- X return(1);
- X
- X /* Dispatch to general password checker */
- X return(checkpasswd(theUser.ui_uid, new));
- X}
- X
- X/*
- X * pw_replace - Replace password in Userinfo database
- X */
- Xpw_replace(new, current)
- Xchar *new, /* New password (plaintext) */
- X *current; /* Current password (plaintext) [unused] */
- X{
- X userptr newu; /* Temp */
- X int rc; /* Temp */
- X long oldsigs, /* Saved signal mask */
- X blockedsigs = sigmask(SIGINT) | /* Signals to block */
- X sigmask(SIGQUIT) | /* while updating */
- X sigmask(SIGTSTP); /* the database */
- X extern int errno;
- X
- X /*
- X * Password has already been validated by pw_check()
- X */
- X if ((newu = getuserbyuid(theUser.ui_uid)) == NULL)
- X quit(1, "pw_replace: Cannot refetch user information.\n");
- X
- X if (strcmp(new, "@") == 0) {
- X printf("Password removed from %s\n", theUser.ui_name);
- X#ifndef DEBUG
- X syslog(LOG_INFO, "Password removed from %s\n", theUser.ui_name);
- X#endif
- X newu->ui_password[0] = 0;
- X }
- X else {
- X char salt[2];
- X
- X randomstring(salt, sizeof(salt));
- X (void) strcpy(newu->ui_password, crypt(new, salt));
- X if (*new == QUOTEC && priv == P_SU) {
- X char *p = new;
- X
- X while (*p) p++;
- X if (*--p == QUOTEC) {
- X *p = 0;
- X (void) strcpy(newu->ui_password, &new[1]);
- X printf("Setting plain text password.\n");
- X }
- X }
- X }
- X ui_acct(newu)->a_pwchanged = time((time_t *)0);
- X
- X#if 0
- X if (UIRecordChanged(newu))
- X quit(1, "Record synchronization error\n");
- X#endif
- X#ifdef DEBUG
- X printf("replace %s %s\n", theUser.ui_password, newu->ui_password);
- X#else
- X errno = 0;
- X oldsigs = sigblock(blockedsigs);
- X if (lockuser(theUser.ui_uid) < 0) {
- X if (errno == ETXTBSY)
- X quit(1,
- X "pw_replace: Data for %s locked out.\n",
- X theUser.ui_name);
- X else
- X quit(1,
- X "pw_replace: Data lock failure for user %s\n",
- X theUser.ui_name);
- X }
- X rc = UIReplaceEntry(newu);
- X (void) sigsetmask(oldsigs);
- X unlockuser(theUser.ui_uid);
- X if (rc < 0)
- X quit(1, "Userinfo update failure %s\n", UIErrorMessage);
- X#endif
- X}
- X
- X/*
- X * pw_cleanup - cleanup routine
- X */
- Xpw_cleanup()
- X{
- X /* Do nothing */
- X}
- X/* End pw_userinfo.c */
- END_OF_FILE
- if test 6714 -ne `wc -c <'pw_userinfo.c'`; then
- echo shar: \"'pw_userinfo.c'\" unpacked with wrong size!
- fi
- # end of 'pw_userinfo.c'
- fi
- echo shar: End of archive 2 \(of 3\).
- cp /dev/null ark2isdone
- MISSING=""
- for I in 1 2 3 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 3 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
- --
- Clyde Hoover (Shouter-To-Dead-Parrots) |
- UNIX/VMS Services | "Any sufficently advanced technology
- Compuatation Center, UT Austin | is indisguishable from a rigged demo."
- clyde@emx.utexas.edu |
-
-